-- print("你好")
--[[print("hello")
print("hello11")
print("hello22")


print("hello33")
print("hello444")


str1 = "中国"
str2 = '北京'

print(str1)
print(str2)
print(str3)



-- 局部变量
local x = 3

-- 访问全局变量y
--~ print("y = "..y)

-- 定义一个函数
function f()
	-- 全局变量
	y = 5
	local z = 8
	-- 访问局部变量
	print("x = "..x);
end

-- 访问函数
f();

-- 访问全局变量y
print("y = "..y)

-- 访问局部变量z
--~ print("z = "..z)

y = "北京"
-- 访问全局变量y
print("yyyyy = "..y)




a = 5//2
print(a)



str = "abcdefg"
print(#str)




-- 定义一个普通函数，包含两个形参
function f(a, b)
	print(a, b)
end

print("无实参传递")
f()

print("传递一个实参")
f(10)


print("传递两个实参")
f(10, 20)


print("传递三个实参")
f(10, 20, 30)

-- 定义两个普通函数





-- 定义一个普通函数，包含可变参
function f(...)
	local a,b,c,d=...
	print(a, b, c, d)
	print(...)
end


print("传递三个实参")
f(10, 20, 30)


print("传递四个实参")
f(10, 20, 30, 40)


print("传递五个实参")
f(10, 20, 30, 40, 50)





-- 定义一个普通函数，返回两个值
function f(a, b)
	local sum = a + b
	local mul = a * b
	return sum, mul;
end

-- 一次性接收两个值
m, n = f(3, 5)

print(m, n)





-- 定义两个普通函数
function sum(a, b)
	return a + b
end

function mul(a, b)
	return a * b
end

-- 定义一个函数，其参数为另一个函数
function f(m, n, fun)
	local result = fun(m, n)
	print(result)
end


-- 普通调用
f(3, 5, sum);
f(3, 5, mul);

-- 匿名函数调用
f(3, 5, function (a, b)
			return a - b;
		end
);




a = 5
if a>0 then
	print("num > 0")
elseif num == 0 then
	print("num = 0")
else
	print("num < 0")
end




a = 3
--~ while a>0 do
--~ 	print(a)
--~ 	a = a - 1
--~ end


repeat
	print(a)
	a = a - 1
until a <= 0





for i=1, 9 do
	print(i)
	if i == 5 then
		break
	end
end




-- 定义一个数组
cities = {"北京", "上海", "广州"}
cities[4] = "深圳"

for i=1, 4 do
	print("cities["..i.."]="..cities[i])
end

print(cities[0])
print(cities[5])

if cities[5] then
	print("========")
else
	print("++++++++")
end




-- 声明一个空的数组
arr = {}

for i=1, 3 do
	-- 声明一个空的数组
	arr[i] = {}
	for j=1, 2 do
		arr[i][j] = i*j
	end
end

for i=1, 3 do
	for j=1, 2 do
		print(arr[i][j])
	end
end




-- 定义一个map
emp = {name="张三", age=23, depart="销售部"}

-- 通过下标方式操作
emp["gender"] = "男"
print(emp["name"])
print(emp["gender"])

-- 点号方式操作
emp.office = "2nd floor"
print(emp.age)
print(emp.office)




a = "xxx"
b = 3
c = 5

-- 定义一个map，其key为表达式
arr = {
	["emp_"..a] = true,
	[b + c] = "Hello",
	["hi"] = 123
}

print(arr.emp_xxx)
print(arr[8])
print(arr.hi)





emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", "深圳"}


print(emp[1])
print(emp[2])
print(emp[3])
print(emp[4])





-- 定义一个数组、map混合结构
emps = {
	{name="张三", age=23},
	{name="李四", age=24},
	{name="王五", age=25},
	{name="赵六", age=26}
}

for i=1, 4 do
	print(emps[i].name.." : "..emps[i].age)
end




emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", "深圳"}
emp[8] = "天津"

print(table.concat(emp, ","))


print(table.maxn(emp))



cities = {"bj北京", "sh上海", "gz广州", "sz深圳", "tj天津", "gz广州"}


--~ table.insert(cities, 2, "深圳")
--~ table.insert(cities, "天津")

--~ table.remove(cities, 2)
--~ table.remove(cities)

--~ table.sort(cities, function(a,b)
--~ 						return a<b
--~ 				   end
--~           )

table.sort(cities)

print(table.concat(cities, ","))




emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", "深圳"}


-- 遍历emp中的所有数组元素
for i, v in ipairs(emp) do
	print(i, v)
end

-- 遍历emp中的所有元素
for k, v in pairs(emp) do
	print(k, v)
end



-- 导入一个模块
rect = require "rectangle"

-- 访问模块的属性，调用模块的函数
print(rectangle.pi)
print(rectangle.perimeter(3, 5))
print(rectangle.area(3, 5))

print(rect.pi)
print(rect.perimeter(3, 5))
print(rect.area(3, 5))

-- 访问模块中与模块无关的内容
print(goldenRatio)
print(maxCircularArea(3, 5))
--~ print(circularArea(3))


emp = {"北京", nil, name="张三", age=23, "上海", depart="销售部", "广州", "深圳"}

print(emp.x)

-- 声明一个元表
meta = {};

-- 将原始表与元表相关联
setmetatable(emp, meta)

-- 有返回值的情况
--~ meta.__index = function(tab, key)
--~ 	return "通过【"..key.."】访问的值不存在"
--~ end

-- 无返回值的情况
meta.__index = function(tab, key)
	print("通过【"..key.."】访问的值不存在")
end

print(emp.x)
print(emp[2])


emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", "深圳"}

print(emp[5])

-- 声明一个元表
meta = {};

-- 将原始表与元表相关联
setmetatable(emp, meta)

-- 再定义一个普通表
other = {}

other[5] = "天津"
other[6] = "西安"

-- 指定元表为另一个普通表
meta.__index = other

-- 在原始表中若找不到，则会到元表指定的普通表中查找
print(emp[6])




emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", "深圳"}

print(emp[5])

-- 声明一个元表
meta = {};

-- 将原始表与元表相关联
setmetatable(emp, meta)

-- 无返回值的情况
function meta.__newindex(tab, key, value)
	print("新增的key为"..key..", value为"..value)
	-- 将新增的key-value写入到原始表
	rawset(tab, key, value)
end

emp.x = "天津"

print(emp.x)


emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", "深圳"}

-- 声明一个元表
meta = {};

-- 将原始表与元表相关联
setmetatable(emp, meta)

-- 再定义一个普通表
other = {}

-- 元表指定的另一个普通表的作用是，暂存新增加的数据
meta.__newindex = other

emp.x = "天津"

print(emp.x)
print(other.x)




emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", 12, "深圳"}

-- 声明一个元表
meta = {
	__add = function(tab, num)
		-- 遍历tab中的所有元素
		for k, v in pairs(tab) do
			-- 若value为数值类型，则做算术加法
			if type(v) == "number" then
				tab[k] = v + num
			-- 若value为string，则做字符串拼接
			elseif type(v) == "string" then
				tab[k] = v..num
			end
		end

		-- 返回变化过的table
		return tab
	end,  -- 注意，这里必须要添加一个逗号

	__tostring = function(tab)
		str = ""
		-- 字符串拼接
		for k, v in pairs(empsum) do
			str = str.." "..k..":"..v
		end

		return str
	end
};

-- 将原始表与元表相关联
setmetatable(emp, meta)

empsum = emp + 5

print(emp)
print(empsum)




emp = {"北京", name="张三", age=23, "上海", depart="销售部", 59, "广州", "深圳"}

-- 将原始表与匿名元表相关联
setmetatable(emp, {
	__call = function(tab, num, str)
		-- 遍历table
		for k, v in pairs(tab) do
			if type(v) == "number" then
				tab[k] = v + num
			elseif type(v) == "string" then
				tab[k] = v..str
			end
		end

		return tab
	end
})

newemp = emp(5, "-hello")

for k, v in pairs(newemp) do
	print(k..":"..v)
end





-- 导入元表
require "meta"

emp = {"北京", name="张三", age=23, "上海", depart="销售部", "广州", 12, "深圳"}

-- 将原始表与元表相关联
setmetatable(emp, meta)

empsum = emp + 5

print(emp)
print(empsum)


meta.__index = function(tab, key)
	print("通过【"..key.."】访问的值不存在")
	return "这个真没有"
end

print(emp.x)




-- 创建一个名称为animal的对象
animal = {name = "Tom", age = 5}

-- 该方式会报错
--~ animal:bark = function(voice)
--~ 	print(self.name.."在"..voice.."叫")
--~ end

-- 冒号中会自动包含一个self参数，表示当前对象本身，相当于this
function animal:bark(voice)
	print(self.name.."在"..voice.."叫")
end


animal:bark("喵喵")

animal2 = animal

-- 将animal置空
animal = nil
animal2.name = "Jerry"

animal2:bark("汪汪")





-- 创建一个类
Animal = {name = "no_name", age = 0}

function Animal:bark(voice)
	print(self.name.."在"..voice.."叫")
end

-- 为该类添加一个无参构造器
function Animal:new()
	-- 创建一个空表
	a = {}

	-- 为新表指定元表为当前基础类表
	-- 在新表中找不到的key，会从self基础类表中查找
	setmetatable(a, {__index=self})

	-- 返回新表
	return a
end


-- 为该类添加一个带参构造器(下面举例是参数为table的情况)
function Animal:new(obj)

	local a = obj or {}

	setmetatable(a, {__index=self})

	-- 返回新表
	return a
end


animal = Animal:new()
animal2 = Animal:new()
-- 调用带参构造器，实参为一个匿名表
animal3 = Animal:new({type="老鼠"})

--~ print(animal)
--~ print(animal2)

animal.name = "Tom"
animal.age = 8
animal.type = "猫"

print(animal.name.."今年"..animal.age.."岁，它是一只"..animal.type)

function animal2:skill()
	return "小老鼠，会偷油"
end

print(animal2.name.."今年"..animal2.age.."岁，它是"..animal2:skill())


animal3.name = "Jerry"
animal3.age = 5

print(animal3.name.."今年"..animal3.age.."岁，它是一只"..animal3.type)





-- 创建一个类
Animal = {name = "no_name", age = 0}

function Animal:bark(voice)
	print(self.name.."在"..voice.."叫")
end

-- 为该类添加一个无参构造器
function Animal:new()
	-- 创建一个空表
	local a = {}

	-- 为新表指定元表为当前基础类表
	-- 在新表中找不到的key，会从self基础类表中查找
	setmetatable(a, {__index=self})

	-- 返回新表
	return a
end


-- 为该类添加一个带参构造器(下面举例是参数为table的情况)
function Animal:new(obj)

	local a = obj or {}

	setmetatable(a, {__index=self})

	-- 返回新表
	return a
end


-- 为Animal类创建一个子类Cat
Cat = Animal:new({type="波斯猫"})

Cat.eyes = "蓝眼睛"

tomcat = Cat:new()
tomcat.name = "Tom"

print(tomcat.name.."是"..tomcat.eyes.."的"..tomcat.type)


print(tomcat:bark("喵喵"))





-- 创建一个协同线程实例
crt = coroutine.create(
	function (a, b)
		print(a, b , a+b)
		-- 获取正在运行的协同线程实例，thread类型
		tr = coroutine.running();
		print(tr)
		-- 查看协同线程实例的类型
		print(type(tr))
		-- 查看协同线程实例的状态
		print(coroutine.status(crt))
		-- 将当前协同线程实例挂起
		coroutine.yield()
		print("又重新返回到了协同线程")
	end
)

-- 启动协同线程实例
coroutine.resume(crt, 3, 5)

-- 查看crt的类型
print("main-"..type(crt))

-- 查看协同线程实例的状态
print("main-"..coroutine.status(crt))

-- 继续执行协同线程
coroutine.resume(crt)

-- 查看协同线程实例的状态
print("main-"..coroutine.status(crt))




-- 创建一个协同线程实例
crt = coroutine.create(
	function (a, b)
		print(a, b)
		-- 将当前协同线程实例挂起，同时携带两个返回值a*b与a/b
		coroutine.yield(a*b, a/b)
		print("又重新返回到了协同线程")
		-- 返回两个值
		return a+b, a-b
	end
)

-- 启动协同线程，返回三个值
-- 第一个返回值为协同线程启动成功状态
-- 后面的返回值为内置函数的返回值
success, result1, result2 = coroutine.resume(crt, 12, 3)

print(success, result1, result2)


success, result1, result2 = coroutine.resume(crt)

print(success, result1, result2)




-- 创建一个协同函数
cf = coroutine.wrap(
	function (a, b)
		print(a, b)

		-- 获取当前协同函数创建的协同线程
		tr = coroutine.running()

		print("tr的类型为：".. type(tr))

		-- 挂起当前的协同线程
		coroutine.yield(a+1, b+1)

		print("又重新返回到了协同线程")

		return a+b, a*b
	end
)

-- 调用协同函数，启动协同线程
result1, result2 = cf(3, 5)
print(result1, result2)

print("cf的类型为：".. type(cf))

-- 重启挂起的协同线程
result1, result2 = cf(3, 5)
print(result1, result2)




cf = coroutine.wrap(
	function (a, b)
		print(a, b)

		-- 获取当前协同函数创建的协同线程
		tr = coroutine.running()

		print("tr的类型为：".. type(tr))

		-- 挂起当前的协同线程
		coroutine.yield(tr, a+1, b+1)

		print("又重新返回到了协同线程")

		return a+b, a*b
	end
)

-- 调用协同函数，启动协同线程
cftr, result1, result2 = cf(3, 5)
print(result1, result2)

print("cf的类型为：".. type(cf))

-- 重启挂起的协同线程
success, result1, result2 = coroutine.resume(cftr)
print(result1, result2)



-- 以只读方式打开一个文件
file = io.open("info.properties", "r")

-- 指定要读取的文件为file
io.input(file)

-- 读取一行数据
line = io.read("*l")

-- 只要有数据，就一直读下去
while line ~= nil do
	print(line)
	line = io.read("*l")
end

-- 关闭文件
io.close(file)




-- 以追加方式打开一个文件
file = io.open("info.properties", "a")

-- 指定要写入的文件为file
io.output(file)

-- 写入一行数据
io.write("\ngender=male")

io.close(file)




-- 以只读方式打开一个文件
file = io.open("info.properties", "r")

-- 读取一行数据
line = file:read("*l")

-- 只要有数据，就一直读下去
while line ~= nil do
	print(line)
	line = file:read("*l")
end

-- 关闭文件
file:close()




-- 以追加方式打开一个文件
file = io.open("info.properties", "a")

-- 写入一行数据
file:write("\nlevel=P7")

file:close()

]]--

-- 只读方式打开
file = io.open("nums.txt", "r")

pos = file:seek()
print("当前位置："..pos)

-- 读取一行数据
line = file:read("*l")
print(line)

pos = file:seek()
print("读取过一行数据后的位置："..pos)

pos = file:seek("set", 2)
print("返回到文件起始位置的后面第2个位置："..pos)

-- 读取一行数据
line = file:read("*l")
print(line)

pos = file:seek("end", -2)
print("定位到文件最后位置的前面第2个位置："..pos)


-- 读取一行数据
line = file:read("*l")
print(line)

file:close()





